{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "aed4728d",
   "metadata": {},
   "source": [
    "## 1 与生成器交互"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "b83cc877",
   "metadata": {},
   "outputs": [],
   "source": [
    "def generator_function():\n",
    "    print(\"开始执行\")\n",
    "    yield 1\n",
    "    print(\"从yield 1之后继续\")\n",
    "    yield 2\n",
    "    print(\"从yield 2之后继续\")\n",
    "    yield 3\n",
    "    print(\"函数结束\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e28fa863",
   "metadata": {},
   "source": [
    "### 1.1 next()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8047d0d0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始执行\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "# 调用生成器函数不会立即执行函数体，而是返回一个生成器对象\n",
    "gen = generator_function()\n",
    "print(next(gen))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e4c0f0cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "从yield 1之后继续\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "print(next(gen))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "1ae0b7a7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "从yield 2之后继续\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "print(next(gen))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4b128768",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "函数结束\n"
     ]
    },
    {
     "ename": "StopIteration",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mStopIteration\u001b[39m                             Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[11]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mgen\u001b[49m\u001b[43m)\u001b[49m)\n",
      "\u001b[31mStopIteration\u001b[39m: "
     ]
    }
   ],
   "source": [
    "print(next(gen))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "baaad48f",
   "metadata": {},
   "source": [
    "### 1.2 send()方法   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "1679e7f3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始\n",
      "Hello\n",
      "收到了：Python!\n",
      "World\n",
      "又收到了：Generator!\n",
      "Bye\n"
     ]
    }
   ],
   "source": [
    "def interactive_generator():\n",
    "    print(\"开始\")\n",
    "    received = yield \"Hello\" # 第一次send(None)会执行到这里，yield返回\"Hello\"，然后暂停\n",
    "    print(f\"收到了：{received}\")\n",
    "    received2 = yield \"World\"\n",
    "    print(f\"又收到了：{received2}\")\n",
    "    yield \"Bye\"\n",
    "\n",
    "gen = interactive_generator()\n",
    "\n",
    "# 启动生成器，必须用 None 或 next(gen)\n",
    "first_value = gen.send(None) # 启动了，停止在yield \"Hello\"处，返回\"Hello\"，然后暂停\n",
    "print(first_value) # 输出：Hello\n",
    "\n",
    "# 向生成器发送数据到了received，并接收下一个yield的值\n",
    "second_value = gen.send(\"Python!\") # received收到\"Python!\"，yield返回\"World\"，然后暂停\n",
    "print(second_value) # 输出：World\n",
    "\n",
    "third_value = gen.send(\"Generator!\") # received2收到\"Generator!\"，yield返回\"Bye\"，然后暂停\n",
    "print(third_value) # 输出：Bye"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc0975b7",
   "metadata": {},
   "source": [
    "### 1.3 throw(type)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "1f6b91ad",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A\n",
      "捕获到异常：出错了！\n",
      "B\n"
     ]
    }
   ],
   "source": [
    "def throw_demo():\n",
    "    try:\n",
    "        yield \"A\"\n",
    "    except ValueError as e:\n",
    "        print(f\"捕获到异常：{e}\")\n",
    "        yield \"B\"\n",
    "\n",
    "gen = throw_demo()\n",
    "print(next(gen)) # 输出：A\n",
    "print(gen.throw(ValueError(\"出错了！\"))) \n",
    "# 输出：捕获到异常：出错了！\n",
    "# 输出：B"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9b8d2f5",
   "metadata": {},
   "source": [
    "### 1.4 close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "eab7624c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A\n",
      "生成器被关闭了\n"
     ]
    }
   ],
   "source": [
    "def close_demo():\n",
    "    try:\n",
    "        yield \"A\"\n",
    "        yield \"B\" # 这行不会被执行\n",
    "    except GeneratorExit:\n",
    "        print(\"生成器被关闭了\")\n",
    "\n",
    "gen = close_demo()\n",
    "print(next(gen)) # 输出：A\n",
    "gen.close()      # 输出：生成器被关闭了"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58793183",
   "metadata": {},
   "source": [
    "## 2 内存友好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "e31c575e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "THE TRAGEDY OF ROMEO AND JULIET\n"
     ]
    }
   ],
   "source": [
    "def read_large_file_generator(file_path):\n",
    "    with open(file_path, 'r', encoding='utf-8') as f:\n",
    "        for line in f: # 文件对象本身就是一个迭代器，一次只读一行\n",
    "            yield line.strip() # 处理一行，yield一行\n",
    "\n",
    "# 使用\n",
    "for line in read_large_file_generator(r\"C:\\Users\\zhengyang\\learning\\Python\\src\\data\\罗密欧与朱丽叶(英文版)莎士比亚.txt\"):\n",
    "    # 每次循环，内存中只有一行数据\n",
    "    print(line) # 处理这一行数据\n",
    "    break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "098b22b8",
   "metadata": {},
   "source": [
    "## 3 无限序列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "64dfa27e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "def infinite_sequence():\n",
    "    num = 0\n",
    "    while True:\n",
    "        yield num\n",
    "        num += 1\n",
    "\n",
    "# 创建一个从0开始，无限递增的序列\n",
    "numbers = infinite_sequence()\n",
    "\n",
    "print(next(numbers)) # 0\n",
    "print(next(numbers)) # 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7747779b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "mining",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
